import 'dart:convert';
import 'dart:io';

import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:flutter_comm_base_framework/core/BaseApiModel.dart';
import 'package:flutter_comm_base_framework/core/eventbus/event_bus_manager.dart';


/*
  使用示例：
    new HttpCallBack((Map<String,dynamic> result){

    },(int code,String msg){

    });

  * */
class HttpCallBack {
  HttpCallBack(Function onSuccessRet,Function(int code,String message) onFailRet){
    this.onSuccessRet = onSuccessRet;
    this.onFailRet = onFailRet;
  }
  //HttpCallBack(this.onSuccessRet ,this.onFailRet);

  //成功回调
  Function onSuccessRet;//(T result)
  //失败回调
  Function(int code,String message) onFailRet;//(int code,String message)
}

class HttpManager {
  static HttpManager _instance;

  factory HttpManager() => _getInstance();

  static HttpManager _getInstance() {
    if (_instance == null) {
      _instance = new HttpManager._();
    }
    return _instance;
  }

  HttpManager._() {
    dio = _createInstance();
  }

  /// global dio object
  static Dio dio;
  static const int _CONNECT_TIMEOUT = 15000;
  static const int _RECEIVE_TIMEOUT = 15000;

  static const int SUCCESS = 1;
  static int TOKEN_INVALID = -1; //token失效
  static const int ERROR = 0;
  static const String ERROR_MESSAGE = '接口调用失败,请稍后再试!';

  /// http request methods
  static const String GET = 'get';
  static const String POST = 'post';
  static const String PUT = 'put';
  static const String PATCH = 'patch';
  static const String DELETE = 'delete';
  static String baseUrl = '';

  static Function getHeaders = (){
    Map<String, dynamic> header = {};
    return header;
  };

  static bool canProxy = false;
  static String proxyHost = "PROXY 172.16.56.57:8888";

  ///get请求，formatModel为false时，不格式化返回数据,须自行解析
  get(
      String url,
      Map<String, dynamic> headers,
      Map<String, dynamic> param,
      HttpCallBack callBack,
      {bool formatModel = true}
      ) async {
    _requestHttp(
      url,
      headers: headers,
      queryParameters: param,
      method: GET,
      callBack: callBack,
      isFormatModel: formatModel,
    );
  }

  ///参数在url后面
  postForm(
    String url,
    Map<String, dynamic> headers,
    Map<String, dynamic> param,
      HttpCallBack callBack,
  ) async {
    _requestHttp(
      url,
      headers: headers,
      queryParameters: param,
      method: POST,
      callBack: callBack,
    );
  }

  ///参数在body中
  postForm1(
      String url,
      Map<String, dynamic> headers,
      Map<String, dynamic> param,
      HttpCallBack callBack,
      ) async {
    _requestHttp(
      url,
      headers: headers,
      data: param,
      method: POST,
      callBack: callBack,
    );
  }

  ///post请求，参数在body中，不格式化返回数据，须自行解析
  postFormBody(
      String url,
      Map<String, dynamic> headers,
      Map<String, dynamic> param,
      HttpCallBack callBack,
      ) async {
    _requestHttp(
      url,
      headers: headers,
      data: param,
      method: POST,
      callBack: callBack,
      isFormatModel: false,
    );
  }

  ///post请求，参数为json格式
  postJSON(
    String url,
    Map<String, dynamic> headers,
    param,
      HttpCallBack callBack,
  ) async {
    _requestHttp(
      url,
      headers: headers,
      data: param,
      method: POST,
      contentType: Headers.jsonContentType,
      callBack: callBack,
    );
  }

  static Future<BaseApiModel> post2Upload(String url,FormData formData,{Map<String, dynamic> headers}) async {
    try {
      dio = _createInstance();
      if (headers != null) {
        dio.options.headers = headers;
      }else{
        dio.options.headers = getHeaders();
      }
      dio.options.contentType = Headers.formUrlEncodedContentType;
      dio.options.receiveTimeout = 60 * 1000;
      Response response = await dio.request(
            url,
            data: formData,
            options: new Options(method: POST),
          );
      if (response.statusCode == HttpStatus.ok) {
        BaseApiModel apiModel = BaseApiModel.json2Object(json.decode(response.data));
        if (apiModel.code == SUCCESS) {
          return apiModel;
        } else {
          print("【文件上传错误】${response.data}\r\n$url,${apiModel.message}[${apiModel.code}]");
          return null;
        }
      }
    } catch (e) {
      print(StackTrace.current);
      return null;
    }
  }

  /// T is Map<String,dynamic>  or List<dynamic>
  static _requestHttp(
    String url, {
    Map<String, dynamic> headers,
    Map<String, dynamic> queryParameters,
    data,
    String contentType = Headers.formUrlEncodedContentType,
    method,
    HttpCallBack callBack,
    bool isFormatModel = true,
  }) async {
    dio = _createInstance();
    if (headers != null) {
      dio.options.headers = headers;
    }else{
      dio.options.headers = getHeaders();
    }
    dio.options.contentType = contentType;
    dio.options.receiveTimeout = _RECEIVE_TIMEOUT;
    try {
      Response response;
      response = await dio.request(
        url,
        queryParameters: queryParameters,
        data: data,
        options: new Options(method: method),
      );
      if (response.statusCode == HttpStatus.ok) {
        if(isFormatModel) {
          BaseApiModel apiModel = BaseApiModel.json2Object(json.decode(response.data));
          if (apiModel.code == SUCCESS) {
            callBack.onSuccessRet(apiModel.result);
          } else if(apiModel.code == TOKEN_INVALID){
            eventBus.fire(EVENT_TOKEN_INVALID);
            callBack.onFailRet(apiModel.code, apiModel.message);
          }else {
            print("【业务异常】${response.data}\r\n$url,headers:${jsonEncode(headers)},queryParameters:${jsonEncode(queryParameters)},data:${data}");
            callBack.onFailRet(apiModel.code, apiModel.message);
          }
        }else{
          callBack.onSuccessRet(json.decode(response.data));
        }
      } else {
        print("【业务异常】${response.statusMessage}\r\n${response.data}\r\n$url,headers:${jsonEncode(headers)},queryParameters:${jsonEncode(queryParameters)},data:${data}");
        callBack.onFailRet(response.statusCode, ERROR_MESSAGE);
      }
    }  catch ( e) {
      print(StackTrace.current);
      print("【请求出错】${e.toString()}\r\n$url,headers:${jsonEncode(headers)},queryParameters:${jsonEncode(queryParameters)},data:${data}");
      callBack.onFailRet(ERROR, ERROR_MESSAGE);
    }
  }

  /// 创建 dio 实例对象
  static Dio _createInstance() {
    //dio = null;
    if (dio == null) {
      /// 全局属性：请求前缀、连接超时时间、响应超时时间
      var options = new BaseOptions(
        baseUrl: baseUrl,
        connectTimeout: _CONNECT_TIMEOUT,
        receiveTimeout: _RECEIVE_TIMEOUT,
        responseType: ResponseType.plain,
//        contentType: Headers.jsonContentType,
        headers: {},
      );
      dio = new Dio(options);
      if(canProxy){
        dio.interceptors.add(new LogInterceptors());
        (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client){
            client.badCertificateCallback = (X509Certificate cert,String host,int port){
              return Platform.isAndroid;
            };
            client.findProxy = (uri){
              return proxyHost;
            };
        };
      }
    }
    return dio;
  }

  /// 清空 dio 对象
  static clear() {
    dio = null;
  }
}

///日志拦截器
class LogInterceptors extends InterceptorsWrapper {
  @override
  Future onRequest(RequestOptions options) {
   /* Log.D("【请求url】${options.baseUrl}${options.path}");
    Log.D("【请求path】${options.path}");
    Log.D("【请求headers】${options.headers.toString()}");
    Log.D("【请求参数query】${options.queryParameters.toString()}");
    Log.D("【请求参数data】${options.data.toString()}");*/
    return super.onRequest(options);
  }

  @override
  Future onResponse(Response response) {
//    print("【返回statusCode】${response.statusCode}");
//    print("【返回headers】${response.headers.toString()}");
//    print("【返回extra】${response.extra.toString()}");
//    print("【返回data】${response.data.toString()}");
    return super.onResponse(response);
  }

  @override
  Future onError(DioError err) {
//    print(err.toString());
//    print(err.response?.toString());
    return super.onError(err);
  }
}
